import asyncio
import time
from logger import logger_main
from llm import generate_text
from wx_api import send_text_message
from config import TYPING_SPEED_PER_SECOND
from typing import List, Any
from msg_stash import push_room_message_stash, RoomMessageDetail, MSG_TYPE

# 任务队列
TASK_QUEUE = asyncio.Queue()


async def push_task(FromUserName: str, room_message_list: List[RoomMessageDetail]):
    """将任务推送到任务队列中"""
    await TASK_QUEUE.put((FromUserName, room_message_list))


def format_withdrawn_info(msg: RoomMessageDetail) -> str:
    """如果消息被撤回，返回格式化的撤回信息字符串。"""
    if msg.is_withdrawn:
        return f"(此消息已于发送后{msg.update_time - msg.create_time}秒被用户撤回)"
    return ""


def build_message_list(room_message_list: List[RoomMessageDetail]) -> tuple[List[Any], str]:
    _message_list = []
    _message_contents_list = []
    for msg in room_message_list:
        withdrwan_msg = format_withdrawn_info(msg)
        # 文本消息
        if msg.message_type == MSG_TYPE.TEXT.value:
            _message_list.append({
                "role": msg.role,
                "content": [{
                    "type": "text",
                    "text": msg.content + withdrwan_msg
                }, {
                    "type": "text",
                    "text": f"[系统通知]你收到了一条消息，发送者的用户名称为:`{msg.send_user_nickname}`.(此消息为自动注入，请不要回复)"
                }]
            })
            _message_contents_list.append(
                f"{msg.send_user_nickname}:{msg.content}{withdrwan_msg}")

        # 图片消息
        elif msg.message_type == MSG_TYPE.IMAGE.value:
            _message_list.append({
                "role": msg.role,
                "content": [{
                    "type": "image_url",
                    "image_url": {
                        "url": f"data:image/jpeg;base64,{msg.image_base64}"
                    }
                }, {
                    "type": "text",
                    "text": f"[系统通知]你收到了一条图片消息，发送者的用户名称为:`{msg.send_user_nickname}`.(此消息为自动注入，请不要回复)" + withdrwan_msg
                }]
            })
            _message_contents_list.append(
                f"{msg.send_user_nickname}:[图片消息]{withdrwan_msg}")

        # 表情符号消息
        elif msg.message_type == MSG_TYPE.EMOJI.value:
            # 假设 emoji 也使用 base64 编码，或者您可以将其视为特殊类型的附件
            _message_list.append({
                "role": msg.role,
                "content": [{
                    "type": "image_url",
                    "image_url": {
                        "url": f"data:image/png;base64,{msg.emoji_base64}"
                    }
                }, {
                    "type": "text",
                    "text": f"[系统通知]你收到了一条表情消息，发送者的用户名称为:`{msg.send_user_nickname}`.(此消息为自动注入，请不要回复)" + withdrwan_msg
                }]
            })
            _message_contents_list.append(
                f"{msg.send_user_nickname}:[表情消息]{withdrwan_msg}")

        # 邀请消息 (作为文本处理)
        elif msg.message_type == MSG_TYPE.INVITE.value:
            _message_list.append({
                "role": msg.role,
                "content": [{
                    "type": "text",
                    "text": msg.content
                },
                    {
                    "type": "text",
                    "text": f"[系统通知]你收到了一条群聊邀请信息，邀请人的用户名称为:`{msg.send_user_nickname}`.(此消息为自动注入，请不要回复)"
                }]
            })
            _message_contents_list.append(
                f"{msg.send_user_nickname}:{msg.content}\n")

        # 拍一拍消息 (作为文本处理)
        elif msg.message_type == MSG_TYPE.PAT.value:
            _message_list.append({
                "role": msg.role,
                "content": [{
                    "type": "text",
                    "text": msg.content + withdrwan_msg
                },
                    {
                    "type": "text",
                    "text": f"[系统通知]你收到了一条拍一拍消息，发送者的用户名称为:`{msg.send_user_nickname}`.(此消息为自动注入，请不要回复)"
                }]
            })
            _message_contents_list.append(
                f"{msg.send_user_nickname}:{msg.content}{withdrwan_msg}"
            )
    return _message_list, "\n".join(_message_contents_list)


async def worker_process():
    while True:
        # 1. 接收任务
        try:
            item = await TASK_QUEUE.get()
            FromUserName, room_message_list = item
            logger_main.info(f"开始处理来自 [{FromUserName}] 的任务队列")

            room_message_list, message_contents = build_message_list(
                room_message_list)

            logger_main.info(f"[{FromUserName}] 处理的消息内容:\n{message_contents}")
            logger_main.info(f"[{FromUserName}] 正在调用 AI 接口生成回复...")
            response = await asyncio.to_thread(generate_text, room_message_list)
            logger_main.info(f"[{FromUserName}] AI 回复内容:\n{response}")
            push_room_message_stash(FromUserName, RoomMessageDetail(
                role="assistant",
                message_id=None,
                message_type=MSG_TYPE.TEXT.value,
                send_user_nickname="assistant",
                content=response.replace("\n", ""),
                create_time=int(time.time()),
                update_time=int(time.time()),
            ))
            lines = response.split('\n')
            new_lines = [line for line in lines if line]
            is_first_message = True
            for sentence in new_lines:
                if is_first_message:
                    is_first_message = False
                else:
                    delay_time = max(
                        len(sentence) / TYPING_SPEED_PER_SECOND, 1)
                    await asyncio.sleep(delay_time)
                await asyncio.to_thread(send_text_message, FromUserName, sentence)
        except ValueError as ve:
            # 处理特定的已知错误，例如参数错误等
            logger_main.error(f"❌ Worker 任务失败, AI回复错误: {ve}")
        except Exception as e:
            # 捕获所有未预期的错误，无论是网络错误还是编程错误
            logger_main.error(
                f"❌  Worker 任务发生未预期的致命错误！该任务被跳过。错误: {type(e).__name__} - {e}",
                exc_info=True  # 打印完整的错误堆栈，方便调试
            )
        finally:
            TASK_QUEUE.task_done()


async def _test():
    await TASK_QUEUE.put(
        ("57439815998@chatroom", [RoomMessageDetail(
            role="user",
            message_id=None,
            message_type=MSG_TYPE.TEXT.value,
            send_user_nickname="达瓦里氏_源",
            content="学校不让穿？vpn不算吧,应该流量代理应该没事吧，你们估计很多学生都会代理的,总不可能每个人都不让他们代理吧,一般都是行为检测或者长期嗯，有外面的IP有加密行为,或者某个代理ip他们可以检测到",
            create_time=int(time.time()),
            update_time=int(time.time()),
        ), RoomMessageDetail(
            role="user",
            message_id=None,
            message_type=MSG_TYPE.TEXT.value,
            send_user_nickname="Handsomedog",
            content="班主任已经好几次强调不让我们翻墙了,人工智能主任也说了,你的igg,还是http协议,更是明文",
            create_time=int(time.time()),
            update_time=int(time.time()),
        ), RoomMessageDetail(
            role="user",
            message_id=None,
            message_type=MSG_TYPE.TEXT.value,
            send_user_nickname="达瓦里氏_源",
            content="不会吧？→_→要求这么多他们这是要干嘛？这是为了限制什么吗？😳单纯的这种行为应该是没关系的你们学校不会不能用two desk吧？我试过，有些企业公司会把two desk的呃行为也给拦截掉保密单位嗯，也不一定是保密单位有，有些金融机构也是这样就是外部的经过two de skip的所有流量，他全部给他拦截掉了外网的任何机器不能够控制到内网的设备",
            create_time=int(time.time()),
            update_time=int(time.time()),
        )]))

if __name__ == "__main__":
    async def main():
        # 启动 worker 任务
        worker_task = asyncio.create_task(worker_process())

        # 运行测试
        await _test()

        # 等待队列中的所有任务完成
        await TASK_QUEUE.join()

        # 取消 worker 任务
        worker_task.cancel()
        try:
            await worker_task
        except asyncio.CancelledError:
            logger_main.info("测试完成，Worker 任务已取消")

    # 运行主函数
    asyncio.run(main())
